package id.co.shuba.spamobile.task;

import id.co.shuba.spamobile.Sessions;
import id.co.shuba.spamobile.activities.MainActivity;
import id.co.shuba.spamobile.download.Downloader;
import id.co.shuba.spamobile.download.HttpDownloader;
import id.co.shuba.spamobile.services.WebServiceHelper;
import id.co.shuba.spamobile.util.Base64;
import id.co.shuba.spamobile.util.Str;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.X509TrustManager;

import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParserException;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class DownloadUpdateV2Task extends AsyncTask<String, Object, AsyncTaskResult<String>> implements Observer {
	private ProgressBar _bar;	
	private long _checksum;	
	private String _fileName;
	private HttpDownloader _downloader;
	private TextView _txtStatus;
	
	public DownloadUpdateV2Task(ProgressBar bar, long checksum, String version, TextView txtStatus) {
		_bar = bar;		
		_checksum = checksum;		
		_fileName = "update_"+version+".apk";
		_txtStatus = txtStatus;
	}	
	
	@Override
	protected void onPreExecute() {	
		super.onPreExecute();		
		
		_bar.setProgress(0);
	}
	
	public void setProgressBar(ProgressBar bar) {
		_bar = bar;
	}
	
	public void setTxtStatus(TextView txtStatus) {
		_txtStatus = txtStatus;
	}
	
	public static void trustEveryone() {
		try {
			HttpsURLConnection
					.setDefaultHostnameVerifier(new HostnameVerifier() {
						public boolean verify(String hostname,
								SSLSession session) {
							return true;
						}
					});

			SSLContext context = SSLContext.getInstance("TLS");
			context.init(null, new X509TrustManager[] { new X509TrustManager() {
				public void checkClientTrusted(X509Certificate[] chain,
						String authType) throws CertificateException {
				}

				public void checkServerTrusted(X509Certificate[] chain,
						String authType) throws CertificateException {
				}

				public X509Certificate[] getAcceptedIssuers() {
					return new X509Certificate[0];
				}
			} }, new SecureRandom());
			HttpsURLConnection.setDefaultSSLSocketFactory(context
					.getSocketFactory());

		} catch (Exception e) {
			e.printStackTrace();
		}
	}	
	
    @Override
    protected AsyncTaskResult<String> doInBackground(String... sUrl) {
        try {        	        	       
        	Log.d("Download Update", sUrl[0]);

            URL url = new URL(sUrl[0]);                                    
                        
            File spaDir = new File(Environment.getExternalStorageDirectory(), "spamobile");
            if (!spaDir.exists())
            	spaDir.mkdirs();
                        
            File file = new File(spaDir, _fileName);
            if (file.exists()) {
            	long checksum = checksum(file.getPath());        
                if (checksum == _checksum) {
                	publishProgress(100, "Download Completed");
                	logout();
                	return new AsyncTaskResult<String>(file.getPath());
                } else {
                	//belom ada handle buat restore download
                	file.delete();
                }
            }            	
            
            trustEveryone();
            _downloader = new HttpDownloader(url, spaDir.getPath() + "/", 8, _fileName, this);            
            //downloader.addObserver(this);                        
            //downloader.waitDamnThread();
            
            Log.d("download", "damn completed");
            logout();
            return new AsyncTaskResult<String>(file.getPath());
        } catch (Exception e) {
        	e.printStackTrace();
        	return new AsyncTaskResult<String>(e);
        }        
    }
    
    private void logout() throws IOException, XmlPullParserException, JSONException {
    	WebServiceHelper ws = new WebServiceHelper(_bar.getContext());
		HashMap<String, Object> properties = new HashMap<String, Object>();
		properties.put("aoCode", Sessions.getUser(_bar.getContext()).getAoCode());
		ws.Call("Logout", properties);
    }
    
    @Override
    protected void onProgressUpdate(Object... values) {    
    	super.onProgressUpdate(values);
    	
    	if (values != null && values.length == 2) {
	    	if (_bar != null)
	    		_bar.setProgress((Integer)values[0]);
	    	
	    	if (_txtStatus != null) {    		
	    		_txtStatus.setText(String.valueOf(values[1]));
	    	}
    	}
    }       
    
    @Override
    protected void onPostExecute(AsyncTaskResult<String> result) {    	
    	
    	Context ctx = _bar.getContext();
    	if (result.getError() != null) {
    		Toast.makeText(_bar.getContext(),
    				result.getError().getMessage(),Toast.LENGTH_LONG).show();
    		return;
    	}
    	
    	long checksum = checksum(result.getResult());        
        if (checksum != _checksum) {
        	_txtStatus.setText("File corrupted");
        	Log.d("Download", "WS Checksum: " + _checksum + ", Downloaded Checksum: " + checksum);
        	return;
        }
        
        _txtStatus.setText("Download completed");
        	
    	Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.fromFile(new File(result.getResult())),
        		"application/vnd.android.package-archive");        
        ctx.startActivity(intent);               
    }
    
    public static long checksum(String file) {
		FileInputStream fis = null;
		CheckedInputStream cis = null;
		Adler32 adler = null;
		try{								
			fis = new FileInputStream(file);  
			adler = new Adler32();
			cis = new CheckedInputStream(fis, adler);			
						
			byte[] buffer = new byte[1024];
			while(cis.read(buffer)>=0) {}
			
			return cis.getChecksum().getValue();
		} catch(Exception e){
			e.printStackTrace();
		} finally {
			try {
				if (fis != null) fis.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return -1;
	}
    
    @Override
    protected void onCancelled() {    
    	super.onCancelled();
    	
    	_downloader.cancel();
    }

	@Override
	public void update(Observable observable, Object data) {
		Downloader downloader = (Downloader) observable;
		
		String status = "";
		if (downloader.getState() == Downloader.CANCELLED)
			status = "Download has been cancelled";
		if (downloader.getState() == Downloader.ERROR)
			status = "Error while downloading file. Please restart application";
		if (downloader.getState() == Downloader.COMPLETED)
			status = "Download completed";
		if (downloader.getState() == Downloader.DOWNLOADING) {
			status = "Progress..." + (int)downloader.getProgress() + "%";
		}
		
		publishProgress((int)downloader.getProgress(), status);		
	}
}